package com.redshark.wmm.UI;

import java.util.Set;
import java.util.concurrent.TimeUnit;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;

import com.jjoe64.graphview.GraphViewSeries;
import com.redshark.wmm.MeasurementRequestor;
import com.redshark.wmm.MultimeterFragment;
import com.redshark.wmm.R;
import com.redshark.wmm.MeasurementProcessing.Measurement;

/**
 * @author bujcich
 * 
 */
public class MainActivity extends Activity {

	MultimeterFragment mf;
	final private String MM_FRAGMENT_TAG = "MeterFragment";
	final private String SV_FRAGMENT_TAG = "SingleValueFragment";
	final private String AC_FRAGMENT_TAG = "ACFragment";
	
	
	SingleValueFragment singleValueFragment;
	ACFragment acFragment;
	ButtonFragment buttonFragment;

	public static final int FREQUENCY = 0;
	public static final int RMS_VOLTAGE = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// Setup Views
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_multi_meter);
	}

	@Override
	public void onResume() {
		super.onResume();
		// Get the actionbar
		ActionBar actionBar = getActionBar();

		// Setup Fragments
		FragmentManager fragmentManager = getFragmentManager();

		// Get the button Fragment
		buttonFragment = (ButtonFragment) fragmentManager
				.findFragmentById(R.id.ButtonFragment);

		// Check for MMF
		mf = (MultimeterFragment) fragmentManager
				.findFragmentByTag(MM_FRAGMENT_TAG);

		// If its null, then must be clean opening app, get us a new MMF
		if (mf == null) {
			// Grab our fragment to put the bluetooth and stuff into
			FragmentTransaction fragmentTransaction = fragmentManager
					.beginTransaction();

			mf = new MultimeterFragment();
			fragmentTransaction.add(mf, MM_FRAGMENT_TAG);
			fragmentTransaction.commit();
		}

		// Setup the main fragment, start with Single Value
		// We can always switch if we start in ScopeMode
		FragmentTransaction svfTrans = fragmentManager.beginTransaction();

		singleValueFragment = (SingleValueFragment) fragmentManager
				.findFragmentByTag(SV_FRAGMENT_TAG);
		if (singleValueFragment == null) {
			singleValueFragment = new SingleValueFragment();
			svfTrans.replace(R.id.DisplayFragmentContainer, singleValueFragment, SV_FRAGMENT_TAG);
			svfTrans.commit();
		}
		
		//Get the AC Fragment if it is still around
		acFragment = (ACFragment) fragmentManager
				.findFragmentByTag(AC_FRAGMENT_TAG);
		
		// Recover our app depending on how it died on a config change
		int connectionStatus = mf.getConnectionStatus();
		if (connectionStatus == MultimeterFragment.BT_DISCONNECTED) {
			actionBar.setSubtitle("Disconnected");
			buttonFragment.buttonsEnabled(false);
		} else if (connectionStatus == MultimeterFragment.BT_CONNECTING) {
			actionBar.setSubtitle("Connecting");
			buttonFragment.buttonsEnabled(false);
		} else if (connectionStatus == MultimeterFragment.BT_CONNECTED) {
			actionBar.setSubtitle("Connected");
			buttonFragment.buttonsEnabled(true);
		} else if (connectionStatus == MultimeterFragment.BT_DISCONNECTING) {
			actionBar.setSubtitle("Disconnecting...");
			buttonFragment.buttonsEnabled(false);
		}

	}

	@Override
	protected void onStart() {
		super.onStart();
		// The activity is about to become visible.
	}

	@Override
	protected void onPause() {
		super.onPause();
		// Another activity is taking focus (this activity is about to be
		// "paused").
	}

	@Override
	protected void onStop() {
		super.onStop();
		// The activity is no longer visible (it is now "stopped")
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// The activity is about to be destroyed.
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.multi_meter, menu);
		
		//Battery Level is by default 0, dont show if we are not connected.
		if (mf.getBatteryLevel() > 0) {
			MenuItem batteryItem = menu.add("Battery Level: "
					+ mf.getBatteryLevel() + "%");
			batteryItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
		}

		return true;
	}

	public void connect(MenuItem item) {
		onButtonClick(ButtonFragment.BTN_CONNECT);
	}

	public void onButtonClick(int ButtonID) {
		switch (ButtonID) {
		case ButtonFragment.BTN_CONNECT:
			mf.connect();
			break;
		case R.id.button1:
			mf.createRequestor(MeasurementRequestor.DC_VOLTAGE,
					TimeUnit.MILLISECONDS, 150);
			break;
		case R.id.button2:
			mf.createRequestor(MeasurementRequestor.DC_CURRENT,
					TimeUnit.MILLISECONDS, 150);
			break;
		case R.id.button3:
			mf.createRequestor(MeasurementRequestor.CURRENT_SCOPE_LOW,
					TimeUnit.MILLISECONDS, 250);
			break;
		case R.id.button4:
			mf.createRequestor(MeasurementRequestor.CURRENT_SCOPE_HIGH,
					TimeUnit.MILLISECONDS, 250);
			break;
		case R.id.button5:
			mf.createRequestor(MeasurementRequestor.DIODE,
					TimeUnit.MILLISECONDS, 150);
			break;
		case R.id.button6:
			mf.createRequestor(MeasurementRequestor.RESISTANCE,
					TimeUnit.MILLISECONDS, 1500);
			break;
		case R.id.button7:
			mf.createRequestor(MeasurementRequestor.FREQUENCY,
					TimeUnit.MILLISECONDS, 250);
			break;
		case R.id.button8:
			mf.createScopeRequestor(MeasurementRequestor.SCOPE_1, 0,
					MeasurementRequestor.FREQUENCY, 0, TimeUnit.MILLISECONDS,
					200);
			break;
		default:
			break;
		}

	}

	public void setActionBarSubtitle(String s) {
		ActionBar actionBar = getActionBar();
		actionBar.setSubtitle(s);
	}

	public void setButtonsEnabled(boolean enabled) {
		buttonFragment.buttonsEnabled(enabled);
	}

	public void displayMeasurement(Measurement measurement) {
		if (singleValueFragment == null || !singleValueFragment.isVisible()) {
			switchToSingleValueFrag();
		} else {
			singleValueFragment.setValue(measurement);
		}
	}

	public void displayScopeRMS(Measurement measurement) {
		if (acFragment == null || !acFragment.isVisible()) {
			switchToACFrag();
		} else {
			acFragment.setRMSValue(measurement);
		}

	}

	public void displayScopeFreq(Measurement measurement) {
		if (acFragment == null || !acFragment.isVisible()) {
			switchToACFrag();
		} else {
			acFragment.setFreqValue(measurement);
		}

	}

	public void displayScopeData(GraphViewSeries series, boolean voltageZoomable) {
		if (acFragment == null || !acFragment.isVisible()) {
			switchToACFrag();
		} else {
			acFragment.setGraphData(series);
			acFragment.enableScaling(voltageZoomable);
		}
	}

	public void switchToACFrag() {
		// Create transaction
		if (acFragment == null) {
			acFragment = new ACFragment();
		}
		FragmentTransaction transaction = getFragmentManager()
				.beginTransaction();

		// Replace whatever is in the fragment_container view with this
		// fragment,
		// and add the transaction to the back stack
		transaction.replace(R.id.DisplayFragmentContainer, acFragment, AC_FRAGMENT_TAG);

		// Commit the transaction
		transaction.commit();
	}

	public void switchToSingleValueFrag() {
		// Create transaction
		if (singleValueFragment == null) {
			singleValueFragment = new SingleValueFragment();
		}
		FragmentTransaction transaction = getFragmentManager()
				.beginTransaction();

		// Replace whatever is in the fragment_container view with this
		// fragment,
		// and add the transaction to the back stack
		transaction.replace(R.id.DisplayFragmentContainer, singleValueFragment, SV_FRAGMENT_TAG);

		// Commit the transaction
		transaction.commit();
	}

	public void voltageZoomIn() {
		mf.voltageZoomIn();
	}

	public void voltageZoomOut() {
		mf.voltageZoomOut();
	}

	public void timeZoomIn() {
		// Time Scaling Disabled
		// If you wanted to do this, you may have to reschedule scope because if
		// you
		// increase time between datapoints, your requests may begin to overlap
		// mf.timeZoomIn();
	}

	public void timeZoomOut() {
		// mf.timeZoomOut();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.action_settings:
			AlertDialog alertDialog = new AlertDialog.Builder(this).create();
			alertDialog.setTitle("Reset...");
			alertDialog.setMessage("Are you sure?");
			alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Continue",
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
						}
					});
			// alertDialog.show();

			// Find the value that is already stored.
			String macAddr = getBluetoothSetting();
			int currentIndex = -1;

			// Get the bluetooth devices
			BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
			Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
			CharSequence[] entries = new CharSequence[pairedDevices.size()];
			CharSequence[] entryValues = new CharSequence[pairedDevices.size()];
			int i = 0;
			for (BluetoothDevice dev : pairedDevices) {
				entries[i] = dev.getName();
				entryValues[i] = dev.getAddress();

				// If this is our previous index, note it so we can set that as
				// the default
				if (macAddr.equals(dev.getAddress())) {
					currentIndex = i;
				}

				i++;
			}

			// make a final variable we can access later
			final CharSequence[] completeEntryValues = entryValues;

			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setTitle("Choose a paired Bluetooth device:");
			builder.setSingleChoiceItems(entries, currentIndex,
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							String mac_addr = completeEntryValues[which]
									.toString();

							setBluetoothSetting(mac_addr);
							dialog.dismiss();

						}
					});
			builder.setCancelable(true);
			builder.setNegativeButton("Cancel",
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					});
			builder.show();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void setBluetoothSetting(String macAddr) {
		SharedPreferences sharedPref = PreferenceManager
				.getDefaultSharedPreferences(getApplicationContext());
		SharedPreferences.Editor editor = sharedPref.edit();
		editor.putString("bluetooth_mac", macAddr);
		editor.commit();
	}

	private String getBluetoothSetting() {
		SharedPreferences sharedPref = PreferenceManager
				.getDefaultSharedPreferences(getApplicationContext());
		return sharedPref.getString("bluetooth_mac", "");
	}

}
